﻿using MS_Entity;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;

namespace MS_UI
{
    public partial class FrmIOVarConfig : Form
    {
        public FrmIOVarConfig()
        {
            InitializeComponent();
            this.Load += FrmIOVarConfig_Load;
            this.dgv_data.AutoGenerateColumns = false;
        }

        private void FrmIOVarConfig_Load(object sender, EventArgs e)
        {
            this.VarList = CommonMethod.LoadXML(VarPath);
            this.VarAlarmList =   CommonMethod.LoadAlarmXml(VarAlarmPath);
            UpdataDGV();
        } 
        
        // Modbus变量List集合
        private List<Variable_Modbus> VarList = new List<Variable_Modbus>();
        // Modbus报警变量List集合
        private List<VarAlarm_Modbus> VarAlarmList = new List<VarAlarm_Modbus>();
        // 创建Modbus变量路径
        private string VarPath = Application.StartupPath + "\\ConfigFile\\" + "Variable_Modbus.xml";
        // 创建Modbus报警变量路径
        private string VarAlarmPath = Application.StartupPath + "\\ConfigFile\\" + "VarAlarm_Modbus.xml";
        // 创建StoreArea路径
        private string StoreAreaPath = Application.StartupPath + "\\ConfigFile\\" + "StoreArea.xml";
        // 创建保存完成标志位
        private bool IsSaved = false;


        private void btn_New_Click(object sender, EventArgs e)
        {
            Frm_NewVar_Mod objFrm = new Frm_NewVar_Mod();
            objFrm.ShowDialog();
            DialogResult dr = objFrm.DialogResult;
            if (dr == DialogResult.OK)
            { 
                this.VarList.Add(objFrm.var);
                if (objFrm.varAlarm != null)
                {
                    this.VarAlarmList.Add(objFrm.varAlarm);
                }
            }
            UpdataDGV();
        }

        private void UpdataDGV()
        {
            this.dgv_data.DataSource = null;
            this.dgv_data.DataSource = this.VarList;
        }

        #region 保存
        private void btn_Save_Click(object sender, EventArgs e)
        {
            // 保存分三步
            try
            {
                // 第一步：保存Modbus变量到XML文件
                XmlDocument rootxml = new XmlDocument();
                XmlElement rootnode = rootxml.CreateElement("Root");
                foreach (Variable_Modbus item in this.VarList)
                {
                    XmlElement xmle = rootxml.CreateElement("Variable");
                    CommonMethod.XMLAttibuteAppend(rootxml, "VarName", item.VarName, xmle);
                    CommonMethod.XMLAttibuteAppend(rootxml, "Address", item.Address, xmle);
                    CommonMethod.XMLAttibuteAppend(rootxml, "DataType", item.DataType, xmle);
                    CommonMethod.XMLAttibuteAppend(rootxml, "StoreArea", item.StoreArea, xmle);
                    CommonMethod.XMLAttibuteAppend(rootxml, "Note", item.Note, xmle);
                    CommonMethod.XMLAttibuteAppend(rootxml, "IsFilling", item.IsFilling, xmle);
                    CommonMethod.XMLAttibuteAppend(rootxml, "IsAlarm", item.IsAlarm, xmle);
                    CommonMethod.XMLAttibuteAppend(rootxml, "IsReport", item.IsReport, xmle);
                    CommonMethod.XMLAttibuteAppend(rootxml, "AbsoluteAddress", item.AbsoluteAddress, xmle);
                    rootnode.AppendChild(xmle);
                }
                rootxml.AppendChild(rootnode);
                if (File.Exists(VarPath)) 
                {
                    File.Delete(VarPath);
                }
                rootxml.Save(VarPath);

                // 第二步：保存存储区变量到XML文件
                List<StoreArea> storeList = Calculate();
                XmlDocument rootxml1 = new XmlDocument();
                XmlElement rootnode1 = rootxml1.CreateElement("Root");
                foreach (StoreArea item in storeList)
                {
                    XmlElement xmle1 = rootxml1.CreateElement("StoreArea");
                    CommonMethod.XMLAttibuteAppend(rootxml1, "StoreType", item.StoreType, xmle1);
                    CommonMethod.XMLAttibuteAppend(rootxml1, "StartReg", item.StartReg.ToString(), xmle1);
                    CommonMethod.XMLAttibuteAppend(rootxml1, "Length", item.Length.ToString(), xmle1);
                    rootnode1.AppendChild(xmle1);
                }
                rootxml1.AppendChild(rootnode1);
                if (File.Exists(StoreAreaPath))
                {
                    File.Delete(StoreAreaPath);
                }
                rootxml1.Save(StoreAreaPath);

                // 第三步：保存报警变量到XML文件
                XmlDocument rootxml2 = new XmlDocument();
                XmlElement rootnode2 = rootxml2.CreateElement("Root");
                foreach (VarAlarm_Modbus item in this.VarAlarmList)
                {
                    XmlElement xmle2 = rootxml2.CreateElement("VarAlarm");
                    CommonMethod.XMLAttibuteAppend(rootxml2, "VarName", item.VarName, xmle2);
                    string alarm = string.Empty;
                    foreach (Alarm it in item.VarAlarm)
                    {
                        alarm += it.AlarmType + ";" + it.AlarmValue.ToString() + ";" + it.Priorty.ToString() + ";" + it.Note + "|";
                    }
                    CommonMethod.XMLAttibuteAppend(rootxml2, "Alarm", alarm, xmle2);
                    rootnode2.AppendChild(xmle2);
                }
                rootxml2.AppendChild(rootnode2);
                if (File.Exists(VarAlarmPath))
                {
                    File.Delete(VarAlarmPath);
                }
                rootxml2.Save(VarAlarmPath);
            }
            catch (Exception ex)
            {
                MessageBox.Show("保存出错" + ex.Message, "保存提示");
                return;
            }
            MessageBox.Show("保存成功", "保存提示");
            IsSaved = true;
            UpdataDGV();
        }
        #endregion
        
        #region 根据当前变量集合进行自动计算，计算出存储区域的集合
        private List<StoreArea> Calculate()
        {
            List<StoreArea> StoreList = new List<StoreArea>();
            List<Variable_Modbus> List_0x = new List<Variable_Modbus>();
            List<Variable_Modbus> List_1x = new List<Variable_Modbus>();
            List<Variable_Modbus> List_3x = new List<Variable_Modbus>();
            List<Variable_Modbus> List_4x = new List<Variable_Modbus>();
            foreach (Variable_Modbus item in VarList)
            {
                if (item.StoreArea == "01 Coil Status(0x)")
                {
                    List_0x.Add(item);
                }
                if (item.StoreArea == "02 Input Status(1x)")
                {
                    List_1x.Add(item);
                }
                if (item.StoreArea == "03 Holding Registers(4x)")
                {
                    List_4x.Add(item);
                }
                if (item.StoreArea == "04 Input Registers(3x)")
                {
                    List_3x.Add(item);
                }
            }
            if (List_0x.Count > 0)
            {
                StoreList.Add(new StoreArea()
                {
                    StoreType = "01 Coil Status(0x)",
                    StartReg = AnalyseVar(List_0x)[0],
                    Length = AnalyseVar(List_0x)[1]
                }); ;
            }
            if (List_4x.Count > 0)
            {
                StoreList.Add(new StoreArea()
                {
                    StoreType = "03 Holding Register(4x)",
                    StartReg = AnalyseVar(List_4x)[0],
                    Length = AnalyseVar(List_4x)[1]
                });
            }
            return StoreList;
        }

        private List<int> AnalyseVar(List<Variable_Modbus> list)
        {
            List<int> ResultList = new List<int>(2);
            List<int> AddressList = new List<int>();
            int Start = 0;
            int End = 0;
            int Length = 0;
            string DataType = string.Empty;
            foreach (Variable_Modbus item in list)
            {
                AddressList.Add(int.Parse(item.Address));
            }
            Start = GetMin(AddressList);
            End = GetMax(AddressList);
            foreach (Variable_Modbus item in list)
            {
                if (item.Address == End.ToString())
                {
                    DataType = item.DataType;
                }
            }
            switch (DataType)
            {
                case "Bool":
                    Length = End - Start + 1;
                    break;
                case "Float":
                    Length = End - Start + 2;
                    break;
                case "Float Inverse":
                    Length = End - Start + 2;
                    break;
                case "Long":
                    Length = End - Start + 2;
                    break;
                case "Long Inverse":
                    Length = End - Start + 2;
                    break;
                case "Double":
                    Length = End - Start + 4;
                    break;
                case "Double Inverse":
                    Length = End - Start + 4;
                    break;
                default:
                    Length = End - Start + 2;
                    break;
            }
            ResultList.Add(Start);
            ResultList.Add(Length);
            return ResultList;
        }


        private int GetMax(List<int> addressList)
        {
            int temp = addressList[0];
            foreach (var item in addressList)
            {
                if (item > temp)
                {
                    temp = item;
                }
            }
            return temp;
        }


        private int GetMin(List<int> addressList)
        {
            int temp = addressList[0];
            foreach (var item in addressList)
            {
                if (item < temp)
                {
                    temp = item;
                }
            }
            return temp;
        }
        #endregion



        private void btn_Update_Click(object sender, EventArgs e)
        {
            if (this.dgv_data.SelectedRows.Count > 0)
            {
                int index = this.dgv_data.CurrentRow.Index;
                Variable_Modbus ModVar = this.VarList[index];
                VarAlarm_Modbus AlarmVar = new VarAlarm_Modbus();
                if (ModVar.IsAlarm == "1")
                {
                    foreach (VarAlarm_Modbus item in this.VarAlarmList)
                    {
                        if (item.VarName == ModVar.VarName)
                        {
                            AlarmVar = item;
                        }
                    }
                }
                Frm_ModVar_Mod objFrm = new Frm_ModVar_Mod(ModVar,AlarmVar);
                DialogResult dr = objFrm.ShowDialog();
                if (dr == DialogResult.OK)
                {
                    this.VarList[index] = objFrm.var;
                    VarAlarm_Modbus varAlarm = objFrm.varAlarm;
                    if (varAlarm != null)
                    {
                        // 判断报警是新增还是修改
                        if (!SelectVarAlarm(varAlarm,VarAlarmList))
                        {
                            this.VarAlarmList.Add(varAlarm);
                        }
                        else
                        {
                            for (int i = 0; i < this.VarAlarmList.Count;i++)
                            {
                                if (this.VarAlarmList[i].VarName == varAlarm.VarName)
                                {
                                    this.VarAlarmList[i] = varAlarm;
                                      break;
                                }
                            }
                        }
                    }
                }
                UpdataDGV();
            }
        }

        /// <summary>
        /// 用于判断报警变量是新增还是修改，True为修改，False为新增
        /// </summary>
        /// <param name="AlarmVar"></param>
        /// <param name="VarAlarmList"></param>
        /// <returns></returns>
        private bool SelectVarAlarm(VarAlarm_Modbus AlarmVar,List<VarAlarm_Modbus> VarAlarmList)
        {
            string str = string.Empty;
            bool Res = false;
            foreach (VarAlarm_Modbus item in VarAlarmList)
            {
                if (item.VarName == AlarmVar.VarName)
                {
                    Res = true;
                }
            }
            return Res;
        }

        private void dgv_data_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            btn_Update_Click(null, null) ;
        }

        private void btn_Delete_Click(object sender, EventArgs e)
        {
            if (this.dgv_data.SelectedRows.Count > 0)
            {
                int index = this.dgv_data.CurrentRow.Index;
                this.VarList.RemoveAt(index);
                string varName = this.VarList[index].VarName;
                for (int i = 0; i < this.VarAlarmList.Count; i++)
                {
                    if (this.VarAlarmList[i].VarName == varName)
                    {
                        this.VarAlarmList.RemoveAt(i);
                    }
                }
            }
            UpdataDGV();
        }

        private void dgv_data_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            new DataGridViewStyle().DgvRowPostPaint(this.dgv_data, e);
        }

        private void FrmIOVarConfig_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (IsSaved == false)
            {
                DialogResult result = MessageBox.Show("是否保存修改内容？","退出询问",MessageBoxButtons.OKCancel,MessageBoxIcon.Question);
                if (result == DialogResult.Cancel)
                {
                    IsSaved = true;
                    return;
                }
                else
                {
                    btn_Save_Click(null,null);
                }
            }
        }
    }
}